#include "../lib_include/Logger.h"
#include "../lib_include/CurrentThread.h"
#include "../lib_include/Timestamp.h"
//#include "../lib_include/TimeZone.h"

#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <sstream>

namespace netlib
{


__thread char t_errnobuf[512];  // 存储错误码对应的描述信息
__thread char t_time[64];       // 当前时间的格式化字符串
__thread time_t t_lastSecond;   // 线程运行的秒数


// strerror_r(int errnum, char *buf, size_t n)
// 传入一个错误码，系统将错误码详细的描述信息输出到buf中，n为buf的大小
const char* strerror_tl(int savedErrno) // 获得错误码的详细描述
{ return strerror_r(savedErrno, t_errnobuf, sizeof t_errnobuf); }

// 日志等级变量初始化
Logger::LogLevel initLogLevel()
{
    if (::getenv("NETLIB_LOG_TRACE")) // getenv获取环境变量netlib_LOG_TRACE
        return Logger::TRACE;
    else if (::getenv("NETLIB_LOG_DEBUG"))
        return Logger::DEBUG;
    else // 如果没有定义netlib_LOG_TRACE、netlib_LOG_DEBUG两个环境变量，则默认采用INFO等级
        return Logger::INFO;
}

Logger::LogLevel g_logLevel = initLogLevel(); // 日志等级变量定义

const char* LogLevelName[Logger::NUM_LOG_LEVELS] =
{
    "TRACE ",
    "DEBUG ",
    "INFO  ",
    "WARN  ",
    "ERROR ",
    "FATAL ",
};


class T // 模板类，判断传入的字符串与和长度是否匹配
{
public:
    T(const char* str, unsigned len)
        :str_(str),
         len_(len)
    { assert(strlen(str) == len_); }

  const char* str_;
  const unsigned len_;

}; // class T end

inline LogStream& operator<<(LogStream& s, T v)
{
    s.append(v.str_, v.len_);
    return s;
}

inline LogStream& operator<<(LogStream& s, const Logger::SourceFile& v)
{
    s.append(v.data_, v.size_);
    return s;
}

LogFile* g_logfile = nullptr;
// LogFile* g_logfile = new LogFile("../log/testlog ", 1024 * 64);

void OutputFuncs(const char* msg,int len)
{
    g_logfile->append(msg, len);
}

void USER_Flush()
{
    g_logfile->flush();
}

void defaultOutput(const char* msg, int len) // 默认输出
{
    size_t n = fwrite(msg, 1, len, stdout); // 默认输出为std标准输出
    (void)n;
}

void defaultFlush() { fflush(stdout); } // 清理缓冲区

Logger::OutputFunc g_output = defaultOutput;    // IO输出流
Logger::FlushFunc g_flush = defaultFlush;       // 清理缓冲区
// TimeZone g_logTimeZone;

} // namespace netlib end

using namespace netlib;

Logger::Impl::Impl(LogLevel level, int savedErrno, const SourceFile& file, int line)
  : time_(Timestamp::now()),
    stream_(),
    level_(level),
    line_(line),
    basename_(file)
{
    formatTime(); // 格式化时间

    CurrentThread::tid(); // 缓存当前线程ID

    // 向流输出当前线程ID的字符串形式
    stream_ << T(CurrentThread::tidString(), CurrentThread::tidStringLength());

    // 向流输出当前日志等级
    stream_ << T(LogLevelName[level], 6);

    // 如果错误码不为0，则输出相应的错误码
    if (savedErrno != 0)
        stream_ << strerror_tl(savedErrno) << " (errno=" << savedErrno << ") ";
}

void Logger::Impl::formatTime() // 格式化当前时间
{
    //printf("%d\n",strlen(time_.toFormattedString(false).c_str()));
    stream_ << T(time_.toFormattedString(false).c_str(), 20);
    //stream_ << time_.toFormattedString(false).c_str();
    // 得到当前微秒数
    // int64_t microSecondsSinceEpoch = time_.microSecondsSinceEpoch();

    // 计算出秒数
    // time_t seconds = static_cast<time_t>(microSecondsSinceEpoch / Timestamp::kMicroSecondsPerSecond);

    // 计算秒数小数点
    // int microseconds = static_cast<int>(microSecondsSinceEpoch % Timestamp::kMicroSecondsPerSecond);

    // if (seconds != t_lastSecond) // 更新线程的秒数时间
    // {
    //     t_lastSecond = seconds;
    //     struct tm tm_time;
    //     if (g_logTimeZone.valid())
    //         tm_time = g_logTimeZone.toLocalTime(seconds);
    //     else
    //         ::gmtime_r(&seconds, &tm_time);

    //     int len = snprintf(t_time, sizeof(t_time), "%4d%02d%02d %02d:%02d:%02d",
    //         tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
    //         tm_time.tm_hour, tm_time.tm_min, tm_time.tm_sec);
    //     assert(len == 17); (void)len;
    // }

    // if (g_logTimeZone.valid())
    // {
    //     Fmt us(".%06d ", microseconds);
    //     assert(us.length() == 8);
    //     stream_ << T(t_time, 17) << T(us.data(), 8);
    // }
    // else
    // {
    //     Fmt us(".%06dZ ", microseconds);
    //     assert(us.length() == 9);
    //     stream_ << T(t_time, 17) << T(us.data(), 9);
    // }
}

void Logger::Impl::finish() // IO对象输出文件名和代码行号
{ stream_ << " - " << basename_ << ':' << line_ << '\n'; }


Logger::Logger(SourceFile file, int line)
  : impl_(INFO, 0, file, line)
{ }

Logger::Logger(SourceFile file, int line, LogLevel level, const char* func)
  : impl_(level, 0, file, line)
{ impl_.stream_ << func << ' '; } // impl_之后剩下函数名未输出，手动输出到IO流

Logger::Logger(SourceFile file, int line, LogLevel level)
  : impl_(level, 0, file, line)
{ }

Logger::Logger(SourceFile file, int line, bool toAbort)
  : impl_(toAbort?FATAL:ERROR, errno, file, line) // toAbort为真则输出日志后立即退出程序
{ }

Logger::~Logger()
{
    impl_.finish(); // IO对象输出文件名和代码行号

    // 得到IO流的缓冲区，引用形式不拷贝
    const LogStream::Buffer& buf(stream().buffer());

    if(g_logfile)
    {
        setOutput(OutputFuncs);
        setFlush(USER_Flush);
    }

    // 将缓冲区的数据输出到设置好的输出流，默认std标准输出
    g_output(buf.data(), buf.length());

    // 如果日志等级为FATAL，则终止程序
    if (impl_.level_ == FATAL)
    {
        g_flush();      // 清理输出缓冲区
        //printf("have a LOG_FATAL\n");
        //exit(0);
        abort();        // 终止程序且不清理，配合core dump使用
    }
}

// 设置日志等级
void Logger::setLogLevel(Logger::LogLevel level) { g_logLevel = level; }

void Logger::setOutput(OutputFunc out) { g_output = out; } // 设置输出流

void Logger::setFlush(FlushFunc flush) { g_flush = flush; } // 设置冲洗缓冲区的位置

// void Logger::setTimeZone(const TimeZone& tz) { g_logTimeZone = tz; }